#include "cudaService.h"



void RGB32ToYUV444Interface(uchar *RGB,uchar *y,uchar*u, uchar* v,int w, int h)
{
    auto start = std::chrono::high_resolution_clock::now();
    uchar* d_RGB,*d_y,*d_u,*d_v;
    cudaMalloc((void**)&d_RGB,4*w*h*sizeof(uchar));
    cudaMalloc((void**)&d_y,w*h*sizeof(uchar));
    cudaMalloc((void**)&d_u,w*h*sizeof(uchar));
    cudaMalloc((void**)&d_v,w*h*sizeof(uchar));
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    cout << "创建cuda内存的时间: " << duration.count()<<"\n";
    //拷贝到gpu
    start = std::chrono::high_resolution_clock::now();
    cudaMemcpy( d_RGB, RGB, 4*w*h*sizeof(uchar), cudaMemcpyHostToDevice);
    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    cout << "cpu-GPU的拷贝的时间: " << duration.count()<<"\n";
    //配置gpu线程模型
    int blockSize = 256;
    int gridSize = (w*h + blockSize - 1) / blockSize;
    start = std::chrono::high_resolution_clock::now();
    RGB32ToYUV444<<<gridSize, blockSize>>>(d_RGB,d_y,d_u,d_v,w,h);
    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    cout << "RGB32ToYUV444的时间: " << duration.count()<<"\n";
    cudaMemcpy( y, d_y, w*h*sizeof(uchar), cudaMemcpyDeviceToHost);
    cudaMemcpy( u, d_u, w*h*sizeof(uchar), cudaMemcpyDeviceToHost);
    cudaMemcpy( v, d_v, w*h*sizeof(uchar), cudaMemcpyDeviceToHost);
    //释放
    cudaFree(d_RGB);
    cudaFree(y);
    cudaFree(u);
    cudaFree(v);
}

__global__ void RGB32ToYUV444(uchar *RGB, uchar *y, uchar *u, uchar *v, int w, int h)
{
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    if(tid<w*h){
        y[tid] = 0.299*(int)RGB[4*tid] + 0.587*(int)RGB[4*tid+1] + 0.114*(int)RGB[4*tid+2];
        u[tid] = -0.1684*(int)RGB[4*tid] - 0.3316*(int)RGB[4*tid+1] +0.5*(int)RGB[4*tid+2] + 128;
        v[tid] = 0.5*(int)RGB[4*tid] - 0.4187*(int)RGB[4*tid+1] -0.0813*(int)RGB[4*tid+2] + 128;
        u[tid] = (u[tid] < 0) ? 0 : ((u[tid] > 255) ? 255 : u[tid]);
        v[tid] = (v[tid] < 0) ? 0 : ((v[tid] > 255) ? 255 : v[tid]);
    }
}
